/*
 * CS_PRACTICE_MATCH_PLAYER.cpp
 *
 *  Created on: 2013. 9. 27.
 *      Author: mega@gamevil.com
 */

#include "../../Command.h"

#include "../../Proxy.h"
#include "../../User.h"
#include "../../NLogic/Space.h"
#include "../../NLogic/Item.h"
#include "../../NLogic/Equip.h"
#include "../../NLogic/Static.h"
#include "../../NLogic/Battle.h"
#include "../../NResource/Static.h"

namespace ProjectZ { namespace NCommand {

void SendPacket_CS_PRACTICE_MATCH_PLAYER(User * pUser, User * pOppUser)
{
	::Network::Packet * pAck = ::Network::GETPACKETPOOL()->SEND_NEW();

	*pAck << static_cast<int16_t>(ACK_OK);
	*pAck << static_cast<uint16_t>(pUser->GetCharacterInfo().consecutive_win);		// 본인 연승 정보
	*pAck << pOppUser->GetSocialID().c_str();										// 상대방 카카오톡 ID
	*pAck << pOppUser->GetUserInfo().nickname.c_str();								// 상대방 카카오톡 닉네임

	if (true == pUser->GetSpace()->GetData()._bPVPDummyUser)
		*pAck << static_cast<int>(0);
	else
		*pAck << pOppUser->GetUserSeq();									// 캐릭터 Seq

	*pAck << "";																	// 상대방 Profile URL
	*pAck << static_cast<uint16_t>(pOppUser->GetCharacterInfo().level);
	*pAck << static_cast<uint8_t>(pOppUser->GetCharacterInfo().classtype);

	// 전투펫 TID
	NLogic::Equip * pOppEquip = pOppUser->GetEquip();
	NLogic::Item * pItem = pOppEquip->GetItem(ITEM_EQUIP_POS_PET);
	if (pItem == NULL)
		*pAck << static_cast<int16_t>(-1);
	else
		*pAck << static_cast<int16_t>(pItem->GetData().tid);

	*pAck << static_cast<int8_t>(-1);		// 길드
	*pAck << static_cast<int16_t>(0);		// ??
//	*pAck << pOppUser->GetUserInfo().userseq;
	*pAck << static_cast<int>(0);

	// TODO: 버프 관련 개발 완료시 수정 필요
	*pAck << static_cast<int8_t>(0);		// 사용되고 있는 버프 갯수

	pAck->MakePacket(CMD_SC_MATCH_PLAYER);
	pUser->Send(pAck);
}

void Command::CS_PRACTICE_MATCH_PLAYER(User * pUser, ::Network::Packet * pPacket)
{
	/* message
	 * CS_PRACTICE_MATCH_PLAYER				0x1304
		{
			u8 u8is_guest;			/// 게스트 로그인 여부 0: 	1:
			u16 u16level;			/// 레벨
			u8 u8class_type;		/// 클래스 타입
		}

		SC_MATCH_PLAYER				0x1307
		{
			s16				s16ack;
			u16				u16Victory_count;			//본인 연승 정보
			str				strUser_id;		 			//상대방 카톡 ID
			str				strUser_Nickname;		 	//상대방 카톡 닉네임
			u32				u32slot_seq;				//캐릭터 고유 DB인덱스
			str				strProfile_url;				//프로필 url
			u16				u16Level;					//레벨
			u8				u8Class_type;				//클래스
			s16				s16Pet_tid;					//전투펫 TID (-1: 없음)
			s8				s8Guild_icon;				//길드 계급 아이콘 번호 ( -1: 길드 없음 )
			str				strGuild_name;		 		//길드 이름
			u32				u32Gid;						//gid

			/// 버프관련
			u8 				u8use_buff_count;			//사용되고 있는 버프 갯수
			{
				u8 u8type;						/// 0:승점버프, 1:친구버프, 2:참피온 버프1 , 3:참피온 버프2, 4:길드 버프
				u16	u16skill_tid;
				u8 u8skill_level;
				s16	s16skill_value;
				u16	u16skill_time;
			}
		}
	 *
	 */

	PREPARE_PACKET;

	char isGuest	= 0;
	uint16_t level	= 0;
	char classType	= 0;

	*pPacket >> isGuest >> level >> classType;

	if (1 == isGuest)
	{
		// TODO : Guest 로그인 처리
		return;
	}

	NLogic::Space * pSpace = pUser->GetSpace();
	if (NULL == pSpace)
	{
		DEBUGLOG("CS_PRACTICE_MATCH_PLAYER : pSpace is NULL!!");
		return;
	}

	if (pUser->GetEnumState() != User::EnumState::__NONE__)
	{
		DEBUGLOG("CS_PRACTICE_MATCH_PLAYER : pUser->GetEnumState() != User::EnumState::__NONE__");
		return;
	}

	NLogic::Equip * pEquip = pUser->GetEquip();
	if (NULL == pEquip)
	{
		DEBUGLOG("CS_PRACTICE_MATCH_PLAYER : pEquip is NULL!!");
		return;
	}

	if (pSpace->GetData()._spaceType != NLogic::Space::SpaceType::WORLD)
	{
		DEBUGLOG("CS_PRACTICE_MATCH_PLAYER : pSpace is NOT WORLD!!");
		return;
	}

	int myLevel = pUser->GetCharacterInfo().level;

	int minLevel = ((myLevel - 3) < 0) ? 0 : myLevel - 3;
	int maxLevel = myLevel + 1;

	User * pDummyUser = NULL;

	auto iter = ::ProjectZ::NProxy::GetUserTree().begin();
	for ( ; iter != ::ProjectZ::NProxy::GetUserTree().end(); ++iter)
	{
		User * pTmp = iter->second;

		if (pTmp->GetEnumState() == User::EnumState::RECONNECT_WAIT)
			continue;

		if (static_cast<int>(pTmp->GetCharacterInfo().level) <= 0)
			continue;

		if (static_cast<int>(pTmp->GetCharacterInfo().level) < minLevel)
			continue;

		if (static_cast<int>(pTmp->GetCharacterInfo().level) > maxLevel)
			continue;

		if (pUser == pTmp)
			continue;

		pDummyUser = pTmp;
		break;
	}

	// 매칭 조건에서 AI 데이터를 찾지 못한 경우, Resource에서 찾는다
	bool bDummyUser = false;
	if (NULL == pDummyUser)
	{
		bDummyUser = true;

		//------------------------------------------------------
		// Changed by spencer(2014.07.02)
		// 성기사 클래스 추가 open/close에 따른 처리
		//------------------------------------------------------
		int iClassCount = EnumCharClass::CLASS_TYPE_MAX;
		if ( false == NResource::Static::Instance().GetContentsOpenResource()->IsOpen(ContentsOpen::NEW_CLASS_PALADIN) )
			iClassCount -= 1;
		int classType = rand() % iClassCount;

		NResource::DummyUserResource::DUMMYUSERTREE & dummytree =
				NResource::Static::InstancePtr()->GetDummyUserResource()->GetDummyUserTree();

		NResource::DummyUserResource::DUMMYUSERTREE::const_iterator citer;

		for (citer = dummytree.begin(); citer != dummytree.end(); ++citer)
		{
			if (static_cast<int>(citer->second->GetCharacterInfo().classtype) != classType)
				continue;

			if (static_cast<int>(citer->second->GetCharacterInfo().level) < minLevel)
				continue;

			if (static_cast<int>(citer->second->GetCharacterInfo().level) > maxLevel)
				continue;

			pDummyUser = citer->second;
			break;
		}

		// 레벨대로 검색해서 매칭에 실패하는 경우 무작위로 매칭
		if (NULL == pDummyUser)
		{
			citer = dummytree.begin();
			std::advance(citer, rand() % dummytree.size());
			pDummyUser = citer->second;
		}
	}

	DEBUGLOG("CS_PRACTICE_MATCH_PLAYER : myUserSeq=%d, oppUserSeq=%d", pUser->GetUserSeq(), pDummyUser->GetUserSeq());

	// 월드에서 제거
	pSpace->LeaveUser(pUser);

	// PVP Space생성 및 유저 입장
	NLogic::Space::Data clsData;
	clsData._maxUser = 1;
	clsData._spaceType = NLogic::Space::SpaceType::PVP_PRACTICE;

	NLogic::Space * pPVP = NLogic::Static::Instance().GETSPACEPOOL()->NEW();
	pPVP->Open(pUser, clsData);
	pPVP->EnterUser(pUser);

	if (true == bDummyUser)
	{
		pPVP->GetData()._bPVPDummyUser = true;
		pPVP->GetData()._PVPDummyUserSeq = pDummyUser->GetUserSeq();
	}

	// 유저의 좌표 설정
	pUser->SetCoordinate(PVP_P1_START_X, PVP_P1_START_Y);

	pUser->GetBattle()->GetData().bReadyFight = false;

	// 유저에게 상대 정보 전송
	SendPacket_CS_PRACTICE_MATCH_PLAYER(pUser, pDummyUser);

	// 전투펫을 장착하고 있다면 스태미너 감소
	if (true == pEquip->IsExistItem(ITEM_EQUIP_POS_PET))
	{
		pEquip->GetItem(ITEM_EQUIP_POS_PET)->DecreaseBattlepetStamina();
	}

	pUser->SetEnumState(User::EnumState::PVP_BATTLE);
}

} /*NCommand*/ } /*ProjectZ*/


